package org.bronycorps.mlptss.domain.layer;

import org.bronycorps.mlptss.domain.controller.GameController;
import org.bronycorps.mlptss.domain.model.Player;
import org.bronycorps.mlptss.manager.CommonAssetManager;
import org.bronycorps.mlptss.manager.preferences.GameConfiguration;
import org.bronycorps.mlptss.screen.LevelScreen;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureWrap;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import com.badlogic.gdx.scenes.scene2d.utils.Align;

public class HudLayer extends AbstractLayer {

	private TextureAtlas atlas;
	private GameConfiguration configuration;
	private BitmapFont font;
	private GameController gameController;
	private CommonAssetManager manager;
	private BitmapFont messageFont;
	private Label[] messages = new Label[2];
	private float timer = 0;
	private Sprite wall;
	private float wallDeltaU2;

	public HudLayer() {
		super();

		this.configuration = GameConfiguration.getInstance();

		this.manager = CommonAssetManager.getInstance();

		// load fonts
		this.font = this.manager.get(this.configuration
				.convertPath(this.configuration.getCurrentMod().getFontFile()),
				BitmapFont.class);

		this.messageFont = this.manager.get(this.configuration
				.convertPath(this.configuration.getCurrentMod().getMenuConfig()
						.getCharacterNameFont()), BitmapFont.class);

		// load atlas
		this.atlas = this.manager.get(this.configuration
				.convertPath(this.configuration.getCurrentMod()
						.getHudLifeAtlas()), TextureAtlas.class);

		addWall(this.configuration.getCurrentMod().getHudMidWallFile(),
				this.configuration.getCurrentMod().getHudMidWallYOffset());

		this.gameController = GameController.getInstance();

		LabelStyle labelStyle = new LabelStyle(this.messageFont, new Color(1,
				1, 1, 1));

		for (int i = 0; i < 2; i++) {
			this.messages[i] = new Label("", labelStyle);
			this.messages[i].setAlignment(Align.center);
			this.messages[i].setPosition(LevelScreen.STAGE_WIDTH / 2,
					LevelScreen.STAGE_HEIGHT / 4 + (i == 0 ? 300 : 0));
			addActor(this.messages[i]);
		}
	}

	@Override
	public void act(float delta) {
		super.act(delta);
		this.timer += delta * 3;
		if (this.timer > 1) {
			this.timer = 0;
		}
	}

	private void addWall(String path, float offset) {
		Texture texture = this.manager.get(
				this.configuration.convertPath(path), Texture.class);
		texture.setWrap(TextureWrap.Repeat, TextureWrap.ClampToEdge);

		this.wall = new Sprite(texture, LevelScreen.STAGE_WIDTH,
				texture.getHeight());
		this.wall.setY(offset);

		this.wallDeltaU2 = this.wall.getU2();

	}

	@Override
	public void draw(SpriteBatch batch, float parentAlpha) {

		// wall

		this.wall.setU(this.timer);
		this.wall.setU2(this.timer + this.wallDeltaU2);

		this.wall.draw(batch, parentAlpha);

		// texts
		this.font.setColor(1, 1, 0, 1);

		this.font.draw(batch, this.gameController.getPlayer(0).getCharacter()
				.getName(), 10, 600);

		this.font.draw(batch, this.gameController.getPlayer(1).getCharacter()
				.getName(), 10, 35);

		this.font.setColor(1, 1, 1, 1);
		this.font.draw(batch, String.format("%05d", this.gameController
				.getPlayer(0).getHighscore()), 500, 600);
		this.font.draw(batch, String.format("%05d", this.gameController
				.getPlayer(1).getHighscore()), 500, 35);

		Player player1 = this.gameController.getPlayer(1);
		Player player0 = this.gameController.getPlayer(0);
		drawLifeBar(batch, player1.getLife(), false);
		drawLifeBar(batch, player0.getLife(), true);

		drawBombBar(batch, player1.getNbBombs(), false);
		drawBombBar(batch, player0.getNbBombs(), true);

		drawContinueBar(batch, player0.getContinues(), true);
		drawContinueBar(batch, player1.getContinues(), false);

		drawChargeBar(batch, player0.getSpecialAttackCharge(),
				player0.getMaxSpecialAttackCharge(), true);
		drawChargeBar(batch, player1.getSpecialAttackCharge(),
				player1.getMaxSpecialAttackCharge(), false);

		this.messages[0].draw(batch, parentAlpha);
		this.messages[1].draw(batch, parentAlpha);
	}

	private void drawBomb(SpriteBatch batch, int posx, boolean posy) {
		Sprite s = this.atlas.createSprite("bomb");
		s.setPosition(465 - posx * 30, posy ? 570 : 10);
		s.draw(batch);
	}

	private void drawBombBar(SpriteBatch batch, int nbBombs,
			boolean isUpperTrack) {
		int counter = 0;
		for (int i = 0; i < nbBombs; i++) {
			drawBomb(batch, counter++, isUpperTrack);
		}
	}

	private void drawChargeBar(SpriteBatch batch, float specialAttackCharge,
			float maxCharge, boolean posy) {

		AtlasRegion maxbackRegion = this.atlas.findRegion("chargeBar-maxback");
		int maxh = (int) (maxCharge / 3 * maxbackRegion.getRegionHeight());
		Texture maxTexture = maxbackRegion.getTexture();
		batch.draw(maxTexture, 4, posy ? 337 : 37, maxbackRegion.getRegionX(),
				maxbackRegion.getRegionY(), maxbackRegion.getRegionWidth(),
				maxh);

		AtlasRegion backRegion = this.atlas.findRegion("chargeBar-back");

		int h = (int) (specialAttackCharge / 3 * backRegion.getRegionHeight());
		Texture texture = backRegion.getTexture();
		batch.draw(texture, 4, posy ? 337 : 37, backRegion.getRegionX(),
				backRegion.getRegionY(), backRegion.getRegionWidth(), h);

		Sprite front = this.atlas.createSprite("chargeBar-front");
		front.setPosition(0, posy ? 330 : 30);
		front.draw(batch);

	}

	private void drawContinue(SpriteBatch batch, int posx, boolean posy) {

		Sprite s = this.atlas.createSprite("medal");
		s.setPosition(580 + posx * 30, posy ? 570 : 7);
		s.draw(batch);
	}

	private void drawContinueBar(SpriteBatch batch, int continues,
			boolean isUpperTrack) {
		int counter = 0;
		for (int i = 0; i < continues; i++) {
			drawContinue(batch, counter++, isUpperTrack);
		}
	}

	private void drawLife(SpriteBatch batch, int level, int posx, boolean posy) {
		String name;
		switch (level) {
		case 2:
			name = "life-full";
			break;
		case 1:
			name = "life-half";
			break;
		default:
			name = "life-empty";
			break;
		}

		Sprite s = this.atlas.createSprite(name);
		s.setPosition(860 + posx * 30, posy ? 560 : 10);
		s.draw(batch);
	}

	private void drawLifeBar(SpriteBatch batch, int life, boolean isUpperTrack) {
		int counter = 0;
		for (int i = 0; i < life / 2; i++) {
			drawLife(batch, 2, counter++, isUpperTrack);
		}
		if (life % 2 == 1) {
			drawLife(batch, 1, counter++, isUpperTrack);
		}
		for (int i = counter; i < 5; i++) {
			drawLife(batch, 0, counter++, isUpperTrack);
		}
	}

	public void setMessage(int idTrack, String message) {
		this.messages[idTrack].setText(message);
	}

}
